home *** CD-ROM | disk | FTP | other *** search
/ Aminet 7 / Aminet 7 - August 1995.iso / Aminet / comm / net / rhslip38_9_030.lha / rhslip / src / device_funcs.c < prev    next >
C/C++ Source or Header  |  1994-01-26  |  52KB  |  2,039 lines

  1. /* $Id: device_funcs.c,v 38.9 1994/01/25 09:04:06 ppessi Exp $
  2. ** $Source: /m/lerppu/u3/projects/Dec93/ohtatcp/amitcp/src/devs/rhslip/RCS/device_funcs.c,v $
  3. ** $State: Exp $
  4. ** $Revision: 38.9 $
  5. ** $Date: 1994/01/25 09:04:06 $
  6. ** $Author: ppessi $
  7. **
  8. ** Amiga SANA-II Example SLIP device driver.
  9. **
  10. ** (C) Copyright 1992 Commodore-Amiga, Inc.
  11. **
  12. */
  13.  
  14. #ifndef USEPRIORITY /* add write requests in priority order */
  15. # define USEPRIORITY    1
  16. #endif
  17. #ifndef DEMANDREAD
  18. # define DEMANDREAD    1
  19. #endif
  20.  
  21. #include "slip_device.h"
  22. #define DEBUG 0
  23. #if DEBUG
  24. #include "syslog.h"
  25. #else
  26. #define debug(x)
  27. #endif
  28.  
  29. #include <dos/dostags.h>
  30. #include <dos/rdargs.h>
  31. #include <intuition/intuition.h>
  32.  
  33. #include <clib/exec_protos.h>
  34. #include <clib/dos_protos.h>
  35. #include <clib/utility_protos.h>
  36. #include <clib/timer_protos.h>
  37. #include <clib/alib_stdio_protos.h>
  38. #include <clib/intuition_protos.h>
  39.  
  40. #include <pragmas/exec_pragmas.h>
  41. #include <pragmas/dos_pragmas.h>
  42. #include <pragmas/utility_pragmas.h>
  43. #include <pragmas/timer_pragmas.h>
  44. #include <pragmas/intuition_pragmas.h>
  45.  
  46. #include <string.h>
  47. #include "device_protos.h"
  48.  
  49. /* Correct prototype for the CheckIO.
  50.  * (The one in clib/exec_protos.h has wrong return value type: BOOL (16 bits) 
  51.  * instead of a pointer (32 bits)!)
  52.  */
  53. struct IORequest * CheckIO(struct IORequest *req);
  54.  
  55. /*
  56. ** External variables and functions
  57. **
  58. */
  59.  
  60. extern struct SLIPDevice *ExtDeviceBase;
  61. extern ULONG IPToNum(STRPTR ipstr);
  62. extern VOID kprintf(STRPTR fmt, ...);
  63.  
  64. const char SLIPName[] = SLIPDEVNAME;
  65.  
  66. /*
  67. ** Device Open vector
  68. **
  69. ** a1 - SANA2 IO Request
  70. ** a6 - Pointer to our device base
  71. ** d0 - Unit number
  72. ** d1 - Flags
  73. **
  74. */
  75.  
  76. ULONG ASM DevOpen(REG(a1) struct IOSana2Req *ios2,
  77.           REG(a6) struct SLIPDevice *SLIPDevice,
  78.           REG(d0) ULONG s2unit,
  79.           REG(d1) ULONG s2flags)
  80. {
  81.     struct SLIPDevUnit *sdu;
  82.     struct TagItem *bufftag;
  83.     struct Library *UtilityBase;
  84.     struct BufferManagement *bm;
  85.     ULONG returncode;
  86.     BOOL status = FALSE;
  87.  
  88.     /* Make sure our open remains single-threaded. */
  89.     ObtainSemaphore(&SLIPDevice->sd_Lock);      /* Enforce single threading since we may need to
  90.                            Wait() when starting up the Unit process */
  91.  
  92. #if DEBUG
  93.     initsyslog();
  94. #endif
  95.     SLIPDevice->sd_Device.lib_OpenCnt++;    /* So we won't expunge ourselves... */
  96.  
  97.     if(s2unit < SD_MAXUNITS)    /* Legal Unit? */
  98.     {
  99.     if(sdu = InitSLIPUnit(s2unit))  /* Initialize the Unit */
  100.     {
  101.         if(UtilityBase = OpenLibrary("utility.library",37L)) /* For Tag functions */
  102.         {
  103.         /* Allocate a structure to store the pointers to the callback routines. */
  104.  
  105.         if(bm = AllocMem(sizeof(struct BufferManagement),MEMF_CLEAR|MEMF_PUBLIC))
  106.         {
  107.             /* Note: I don't complain if I can't find pointers to the callback routines.
  108.                  This is because there are some programs that may need to open me, but
  109.                  will never use any device commands that require the callbacks. */
  110.  
  111.             if(bufftag = FindTagItem(S2_CopyToBuff, (struct TagItem *)ios2->ios2_BufferManagement))
  112.             {
  113.             bm->bm_CopyToBuffer = (SANA2_CTB) bufftag->ti_Data;
  114.             }
  115.  
  116.             if(bufftag = FindTagItem(S2_CopyFromBuff, (struct TagItem *)ios2->ios2_BufferManagement))
  117.             {
  118.             bm->bm_CopyFromBuffer = (SANA2_CFB) bufftag->ti_Data;
  119.             }
  120.  
  121.             AddTail((struct List *)&sdu->sdu_BuffMgmt,(struct Node *)bm);
  122.  
  123.             /* Everything went okay. */
  124.             status = TRUE;
  125.             returncode = 0;
  126.             SLIPDevice->sd_Device.lib_OpenCnt++;
  127.             SLIPDevice->sd_Device.lib_Flags &=~LIBF_DELEXP;
  128.             sdu->sdu_Unit.unit_OpenCnt++;
  129.  
  130.             /* Fix up the initial io request */
  131.             ios2->ios2_BufferManagement = (VOID *)bm;
  132.             ios2->ios2_Req.io_Error = 0;
  133.             ios2->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
  134.             ios2->ios2_Req.io_Unit = sdu;
  135.             ios2->ios2_Req.io_Device = SLIPDevice;
  136.         }
  137.         CloseLibrary(UtilityBase);
  138.         }
  139.     }
  140.     }
  141.     /* See if something went wrong. */
  142.     if(!status)
  143.     {
  144.     ios2->ios2_Req.io_Error = IOERR_OPENFAIL;
  145.     ios2->ios2_Req.io_Unit = (struct Unit *) -1;
  146.     ios2->ios2_Req.io_Device = (struct Device *) -1;
  147.     returncode = IOERR_OPENFAIL;
  148.     }
  149.     SLIPDevice->sd_Device.lib_OpenCnt--;
  150.     ReleaseSemaphore(&SLIPDevice->sd_Lock);
  151.  
  152.     return(returncode);
  153. }
  154.  
  155. /*
  156. ** Device Close vector.
  157. **
  158. ** a1 - IOReq
  159. ** a6 - Device Pointer
  160. **
  161. */
  162.  
  163. BPTR ASM DevClose(REG(a1) struct IOSana2Req *ios2,
  164.           REG(a6) struct SLIPDevice *SLIPDevice)
  165. {
  166.     struct SLIPDevUnit *sdu;
  167.     BPTR seglist = 0L;
  168.  
  169.     ObtainSemaphore(&SLIPDevice->sd_Lock);
  170.  
  171.     sdu = (struct SLIPDevUnit *)ios2->ios2_Req.io_Unit;
  172.  
  173.     /* Trash the io_Device and io_Unit fields so that any attempt to use this
  174.        request will die immediatly. */
  175.  
  176.     ios2->ios2_Req.io_Device = (struct Device *) -1;
  177.     ios2->ios2_Req.io_Unit = (struct Unit *) -1;
  178.  
  179.     /* I always shut the unit process down if the open count drops to zero.
  180.        That way, if I need to expunge, I never have to Wait(). */
  181.  
  182.     sdu->sdu_Unit.unit_OpenCnt--;
  183.     if(!sdu->sdu_Unit.unit_OpenCnt)
  184.     {
  185.     ExpungeUnit(sdu);
  186.     }
  187.  
  188.     SLIPDevice->sd_Device.lib_OpenCnt--;
  189.  
  190.     ReleaseSemaphore(&SLIPDevice->sd_Lock);
  191.  
  192.     /* Check to see if we've been asked to expunge. */
  193.     if(SLIPDevice->sd_Device.lib_Flags & LIBF_DELEXP)
  194.     seglist = DevExpunge(SLIPDevice);
  195.  
  196.     return(seglist);
  197. }
  198.  
  199.  
  200. /*
  201. ** Device Expunge vector
  202. **
  203. ** a6 - Device base
  204. **
  205. ** Note: You may NEVER EVER Wait() in expunge. Period.
  206. **     Don't even *think* about it.
  207. */
  208.  
  209. BPTR ASM DevExpunge(REG(a6) struct SLIPDevice *SLIPDevice)
  210. {
  211.     BPTR seglist;
  212.     ULONG devbase;
  213.     LONG devbasesize;
  214.  
  215.     if(SLIPDevice->sd_Device.lib_OpenCnt)
  216.     {
  217.     /* Sorry, we're busy.  We'll expunge later on
  218.        if we can. */
  219.     SLIPDevice->sd_Device.lib_Flags |= LIBF_DELEXP;
  220.     seglist = (BPTR)0L;
  221.     }
  222.     else
  223.     {
  224.     /* Free up our library base and function table after
  225.        removing ourselves from the library list. */
  226.     Remove((struct Node *)SLIPDevice);
  227.     seglist = SLIPDevice->sd_SegList;
  228.  
  229.     devbase = (ULONG) SLIPDevice;
  230.  
  231.     devbasesize = (ULONG)SLIPDevice->sd_Device.lib_NegSize;
  232.     devbase = devbase - devbasesize;
  233.  
  234.     devbasesize += (ULONG)SLIPDevice->sd_Device.lib_PosSize;
  235.  
  236. #if DEBUG
  237.     uninitsyslog();
  238. #endif
  239.     FreeMem((APTR)devbase,devbasesize);
  240.     ExtDeviceBase = NULL;
  241.     }
  242.     return(seglist);
  243. }
  244.  
  245. /*
  246. ** InitSLIPUnit
  247. **
  248. ** Initialize (if needed) a new SLIP device Unit and process.
  249. **
  250. */
  251.  
  252. struct SLIPDevUnit *InitSLIPUnit(ULONG s2unit)
  253. {
  254.     struct SLIPDevice *SLIPDevice = SLIPBase;
  255.     struct SLIPDevUnit *sdu;
  256.     struct TagItem NPTags[]={NP_Entry, 0, NP_Name, 0, NP_Priority, SLIP_PRI, TAG_DONE, 0};
  257.     struct MsgPort *replyport;
  258.  
  259.     /* Check to see if the Unit is already up and running.  If
  260.        it is, just drop through.  If not, try to start it up. */
  261.  
  262.     if(!SLIPDevice->sd_Units[s2unit])
  263.     {
  264.     /* Open up dos.library */
  265.     if(SLIPDevice->sd_DOSBase = OpenLibrary("dos.library",37L))
  266.     {
  267.         /* Allocate a new Unit structure */
  268.         if(sdu = AllocMem(sizeof(struct SLIPDevUnit), MEMF_CLEAR|MEMF_PUBLIC))
  269.         {
  270.         /* Do some initialization on the Unit structure */
  271.  
  272.         NewList(&sdu->sdu_Unit.unit_MsgPort.mp_MsgList);
  273.         sdu->sdu_Unit.unit_MsgPort.mp_Node.ln_Type = NT_MSGPORT;
  274.         sdu->sdu_Unit.unit_MsgPort.mp_Flags = PA_IGNORE;
  275.         sdu->sdu_Unit.unit_MsgPort.mp_Node.ln_Name = (char *)SLIPName;
  276.  
  277.         sdu->sdu_UnitNum = s2unit;
  278.         sdu->sdu_Device = (struct Device *) SLIPDevice;
  279.  
  280.         /* Try to read in our configuration file */
  281.         if(ReadConfig(sdu))
  282.         {
  283.             /* Start up the unit process */
  284.             if(replyport = CreateMsgPort())
  285.             {
  286.             SLIPDevice->sd_Startup.Msg.mn_ReplyPort = replyport;
  287.             SLIPDevice->sd_Startup.Device = (struct Device *) SLIPDevice;
  288.             SLIPDevice->sd_Startup.Unit = (struct Unit *)sdu;
  289.  
  290.             NPTags[0].ti_Data = (ULONG) &DevProcCEntry;
  291.             NPTags[1].ti_Data = (ULONG) SLIPName;      /* Process name */
  292.             /* Rhialto: use opener's priority */
  293.             NPTags[2].ti_Data = (ULONG) FindTask(NULL)->tc_Node.ln_Pri;
  294.  
  295.             /*ExtDeviceBase = (struct Library *)SLIPDevice;*/
  296.  
  297.             if(sdu->sdu_Proc = CreateNewProc(NPTags))
  298.             {
  299.                 PutMsg(&sdu->sdu_Proc->pr_MsgPort,(struct Message *)&SLIPDevice->sd_Startup);
  300.                 WaitPort(replyport);
  301.                 GetMsg(replyport);
  302.             }
  303.             DeleteMsgPort(replyport);
  304.             }
  305.         }
  306.  
  307.         if(!sdu->sdu_Proc)
  308.         {
  309.             /* The Unit process couldn't start for some reason, so free the Unit structure. */
  310.             FreeMem(sdu,sizeof(struct SLIPDevUnit));
  311.         }
  312.         else
  313.         {
  314.             /* Set up the Unit structure pointer in the device base */
  315.             SLIPDevice->sd_Units[s2unit] = (struct Unit *)sdu;
  316.         }
  317.         }
  318.         CloseLibrary(SLIPDevice->sd_DOSBase);
  319.     }
  320.     }
  321.     return((struct SLIPDevUnit *)SLIPDevice->sd_Units[s2unit]);
  322. }
  323.  
  324. /*
  325. **
  326. ** ExpungeUnit
  327. **
  328. ** Tells a unit process to go away...
  329. **
  330. ** This function is called from the DevClose routine when the open count for a
  331. ** unit reaches zero.  This routine signals the unit process to exit and then
  332. ** waits for the unit process to acknowledge.  The unit structure is then
  333. ** freed.
  334. */
  335.  
  336. VOID ExpungeUnit(struct SLIPDevUnit *sdu)
  337. {
  338.     struct SLIPDevice *SLIPDevice = SLIPBase;
  339.     struct Task *unittask;
  340.  
  341.     unittask = (struct Task *)sdu->sdu_Proc;
  342.  
  343.     sdu->sdu_Proc = (struct Process *)FindTask(0L);
  344.  
  345.     Signal(unittask,SIGBREAKF_CTRL_F);
  346.     Wait(SIGBREAKF_CTRL_F);
  347.  
  348.     SLIPDevice->sd_Units[sdu->sdu_UnitNum] = NULL;
  349.  
  350.     FreeMem(sdu, sizeof(struct SLIPDevUnit));
  351. }
  352.  
  353. /*
  354. **
  355. ** ReadConfig
  356. **
  357. ** Attempt to read in and parse the driver's configuration file.
  358. **
  359. ** The files are named by ENV:SANA2/(c)slipX.config where X is the decimal
  360. ** representation of the device's unit number.
  361. **
  362. */
  363.  
  364. BOOL ReadConfig(struct SLIPDevUnit *sdu)
  365. {
  366.     UBYTE *linebuff,buff[40];
  367.     STRPTR termchar;
  368.     struct RDArgs *rdargs;
  369.     BPTR ConfigFile;
  370.     BOOL status = FALSE;
  371.     ULONG linenum=0;
  372.  
  373.     /* Create the name of our config file.. */
  374.     sprintf(buff,"ENV:SANA2/rhslip%ld.config",(ULONG)sdu->sdu_UnitNum);
  375.     if(ConfigFile = Open(buff,MODE_OLDFILE))
  376.     goto config_open;
  377. #if CSLIP
  378.     sprintf(buff,"ENV:SANA2/cslip%ld.config",(ULONG)sdu->sdu_UnitNum);
  379.     if(ConfigFile = Open(buff,MODE_OLDFILE))
  380.     goto config_open;
  381. #endif
  382.     sprintf(buff,"ENV:SANA2/slip%ld.config",(ULONG)sdu->sdu_UnitNum);
  383.  
  384.     /* ...and open it. */
  385.     if(ConfigFile = Open(buff,MODE_OLDFILE))
  386.     {
  387.     config_open:
  388.     /* Here, I use ReadArgs() to do the file parsing for me. */
  389.  
  390.     if(linebuff = AllocMem(256,MEMF_CLEAR|MEMF_PUBLIC))
  391.     {
  392.         if(rdargs = AllocDosObject(DOS_RDARGS, NULL))
  393.         {
  394.         while(FGets(ConfigFile, linebuff, 255))
  395.         {
  396.             /* ppessi: This is more robust than LONG array */
  397.             struct {
  398.             STRPTR a_SerDevName;
  399.             ULONG *a_SerUnitNum;
  400.             ULONG *a_BaudRate;
  401.             STRPTR a_IPAddr;
  402.             ULONG *a_MTU;
  403.             ULONG  a_CarrierDetect;
  404.             ULONG  a_7Wire;
  405.             ULONG  a_EofMode;
  406.             } args[1];
  407.  
  408.             const UBYTE template[] = 
  409.               "SERNAME/A,"
  410.                 "SERUNIT/A/N,"
  411.               "SERBAUD/A/N,"
  412.               "IPSTR/A,"
  413.               "MTU/K/N,"
  414.               "CD=CARRIERDETECT/S,7WIRE/S,EOF=EOFMODE/S";
  415.  
  416.             linenum++;
  417.             if(linebuff[0] == '#') /* Skip comment lines */
  418.             continue;
  419.  
  420.             rdargs->RDA_Source.CS_Buffer = linebuff;
  421.             rdargs->RDA_Source.CS_Length = 256;
  422.             rdargs->RDA_Source.CS_CurChr = 0;
  423.  
  424.             /* ReadArgs() requires that the line be null-terminated
  425.                or funny things happen. */
  426.  
  427.             termchar = (STRPTR) linebuff + strlen(linebuff);
  428.             *termchar = '\n';
  429.             termchar++;
  430.             *termchar = 0;
  431.  
  432.             memset(args, 0, sizeof(*args));
  433.  
  434.             /* Parse the line...*/
  435.             /* ppessi: New parameters */
  436.             if (ReadArgs(template, (LONG *)args, rdargs))
  437.             {
  438.             strncpy(sdu->sdu_SerDevName, args->a_SerDevName, sizeof(sdu->sdu_SerDevName));
  439.             sdu->sdu_SerUnitNum = *args->a_SerUnitNum;
  440.             sdu->sdu_BaudRate = *args->a_BaudRate;
  441.             sdu->sdu_StAddr = /* Rhialto */
  442.                 sdu->sdu_HwAddr = IPToNum(args->a_IPAddr);
  443.  
  444.             if (args->a_CarrierDetect)
  445.                 sdu->sdu_State |= SLIPUF_CD;
  446.             debug(("Config: CD %d\n", sdu->sdu_State & SLIPUF_CD));
  447.  
  448.             if (args->a_7Wire)
  449.                 sdu->sdu_State |= SLIPUF_7WIRE;
  450.             debug(("Config: 7W %d\n", sdu->sdu_State & SLIPUF_7WIRE));
  451.  
  452.             if (args->a_EofMode)
  453.                 sdu->sdu_State |= SLIPUF_EOFMODE;
  454.             debug(("Config: EOFMODE %d\n", sdu->sdu_State & SLIPUF_EOFMODE));
  455.             
  456.             /* ppessi: some SLIP drivers are broken, break this too... */
  457.             if (args->a_MTU && *args->a_MTU < SLIP_SERIAL_BUFSIZE / 2 - BUF_SLOP) 
  458.             {
  459.                 sdu->sdu_MTU = *args->a_MTU;
  460.             } 
  461.             else 
  462.             {
  463.                 /* 1006 byte max */
  464.                 sdu->sdu_MTU = SLIP_MTU; 
  465.             }
  466.             debug(("Config: MTU=%d\n", sdu->sdu_MTU));
  467.             
  468.             status = TRUE;
  469.             FreeArgs(rdargs);
  470.             break;
  471.             } else {
  472.             struct Library *IntuitionBase;
  473.             struct EasyStruct es;
  474.             if(IntuitionBase = OpenLibrary("intuition.library",37L))
  475.             {
  476.                 es.es_StructSize=sizeof(struct EasyStruct);
  477.                 es.es_Flags=0;
  478.                 es.es_Title=(char *)SLIPName;
  479.                 es.es_TextFormat="Error in configuration file on line %ld.";
  480.                 es.es_GadgetFormat="Okay";
  481.                 EasyRequestArgs(NULL, &es, 0, &linenum);
  482.                 CloseLibrary(IntuitionBase);
  483.             }
  484.             break;
  485.             }
  486.  
  487.         }
  488.         FreeDosObject(DOS_RDARGS,rdargs);
  489.         }
  490.         FreeMem(linebuff, 256);
  491.     }
  492.     Close(ConfigFile);
  493.     }
  494.     return(status);
  495. }
  496.  
  497.  
  498. /*
  499. **
  500. ** BeginIO
  501. **
  502. ** This is the dispatch point for the driver's incoming IORequests.
  503. **
  504. */
  505.  
  506. #define SLIP_IMMEDIATES 0L
  507.  
  508. VOID ASM DevBeginIO(REG(a1) struct IOSana2Req *ios2,
  509.             REG(a6) struct SLIPDevice *SLIPDevice)
  510. {
  511.     ios2->ios2_Req.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  512.  
  513.     if(ios2->ios2_Req.io_Command < S2_END)
  514.     {
  515.     if((1L << ios2->ios2_Req.io_Command) & SLIP_IMMEDIATES)
  516.     {
  517.         PerformIO(ios2);
  518.     }
  519.     else
  520.     {
  521.         ios2->ios2_Req.io_Flags &= ~IOF_QUICK;
  522.         PutMsg((struct MsgPort *)ios2->ios2_Req.io_Unit,(struct Message *)ios2);
  523.     }
  524.     }
  525.     else
  526.     {
  527.     ios2->ios2_Req.io_Error = IOERR_NOCMD;
  528.     TermIO(ios2);
  529.     }
  530. }
  531.  
  532. /*
  533. ** This routine is used to dispatch an IO request either from BeginIO
  534. ** or from the Unit process.
  535. */
  536. VOID PerformIO(struct IOSana2Req *ios2)
  537. {
  538.     struct SLIPDevUnit *sdu;
  539.  
  540.     sdu = (struct SLIPDevUnit *)ios2->ios2_Req.io_Unit;
  541.  
  542.     ios2->ios2_Req.io_Error = 0;
  543.  
  544.     switch(ios2->ios2_Req.io_Command)
  545.     {
  546.     case CMD_READ:            ReadPacket(sdu,ios2);
  547.                     break;
  548.  
  549.     case CMD_WRITE:         WritePacket(sdu,ios2);
  550.                     break;
  551.  
  552.     case S2_DEVICEQUERY:        DeviceQuery(sdu,ios2);
  553.                     break;
  554.  
  555.     case S2_GETSTATIONADDRESS:  GetStationAddress(sdu,ios2);
  556.                     break;
  557.  
  558.     case S2_CONFIGINTERFACE:    ConfigInterface(sdu,ios2);
  559.                     break;
  560.  
  561.     case S2_ADDMULTICASTADDRESS:
  562.     case S2_DELMULTICASTADDRESS:
  563.     case S2_MULTICAST:        ios2->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
  564.                     ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  565.                     TermIO(ios2);
  566.                     break;
  567.  
  568.     case S2_BROADCAST:        WritePacket(sdu,ios2);
  569.                     break;
  570.  
  571.     case S2_TRACKTYPE:        TrackType(sdu,ios2);
  572.                     break;
  573.  
  574.     case S2_UNTRACKTYPE:        UnTrackType(sdu,ios2);
  575.                     break;
  576.  
  577.     case S2_GETTYPESTATS:        GetTypeStats(sdu,ios2);
  578.                     break;
  579.  
  580.     case S2_GETSPECIALSTATS:    GetSpecialStats(sdu,ios2);
  581.                     break;
  582.  
  583.     case S2_GETGLOBALSTATS:     GetGlobalStats(sdu,ios2);
  584.                     break;
  585.  
  586.     case S2_ONEVENT:        OnEvent(sdu,ios2);
  587.                     break;
  588.  
  589.     case S2_READORPHAN:        ReadOrphan(sdu,ios2);
  590.                     break;
  591.  
  592.     case S2_ONLINE:         Online(sdu,ios2);
  593.                     break;
  594.  
  595.     case S2_OFFLINE:        Offline(sdu,ios2);
  596.                     break;
  597.  
  598.     default:            ios2->ios2_Req.io_Error = IOERR_NOCMD;
  599.                     TermIO(ios2);
  600.                     break;
  601.     }
  602. }
  603.  
  604. /*
  605. ** This function returns any device specific statistics that
  606. ** we may have.  Unfortunately, we don't have any SLIP specific
  607. ** statistics.
  608. */
  609. VOID GetSpecialStats(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  610. {
  611.     struct Sana2SpecialStatHeader *stats;
  612.  
  613.     stats = (struct Sana2SpecialStatHeader *)ios2->ios2_StatData;
  614.  
  615. #if CSLIP
  616.     {
  617.     int count;
  618.     struct Sana2SpecialStatRecord *r;
  619.  
  620.     count = stats->RecordCountMax;
  621.     if (count > 11)
  622.         count = 11;
  623.     r = (struct Sana2SpecialStatRecord *)(stats + 1);
  624.     r = &r[count - 1];
  625.  
  626.     switch (count) {
  627.     case 11:
  628.         r->Type = S2SS_CSLIP_I_TOSSED;
  629.         r->String = "i_tossed";
  630.         r->Count = sdu->sdu_slcompress.sls_i_tossed;
  631.         r--;
  632.     case 10:
  633.         r->Type = S2SS_CSLIP_I_ERROR;
  634.         r->String = "i_error";
  635.         r->Count = sdu->sdu_slcompress.sls_i_error;
  636.         r--;
  637.     case 9:
  638.         r->Type = S2SS_CSLIP_I_COMPRESSED;
  639.         r->String = "i_compressed";
  640.         r->Count = sdu->sdu_slcompress.sls_i_compressed;
  641.         r--;
  642.     case 8:
  643.         r->Type = S2SS_CSLIP_I_UNCOMPRESSED;
  644.         r->String = "i_uncompressed";
  645.         r->Count = sdu->sdu_slcompress.sls_i_uncompressed;
  646.         r--;
  647.     case 7:
  648.         r->Type = S2SS_CSLIP_I_IP;
  649.         r->String = "i_ip";
  650.         r->Count = sdu->sdu_slcompress.sls_i_ip;
  651.         r--;
  652.     case 6:
  653.         r->Type = S2SS_CSLIP_O_MISSES;
  654.         r->String = "o_misses";
  655.         r->Count = sdu->sdu_slcompress.sls_o_misses;
  656.         r--;
  657.     case 5:
  658.         r->Type = S2SS_CSLIP_O_SEARCHES;
  659.         r->String = "o_searches";
  660.         r->Count = sdu->sdu_slcompress.sls_o_searches;
  661.         r--;
  662.     case 4:
  663.         r->Type = S2SS_CSLIP_O_COMPRESSED;
  664.         r->String = "o_compressed";
  665.         r->Count = sdu->sdu_slcompress.sls_o_compressed;
  666.         r--;
  667.     case 3:
  668.         r->Type = S2SS_CSLIP_O_UNCOMPRESSED;
  669.         r->String = "o_uncompressed";
  670.         r->Count = sdu->sdu_slcompress.sls_o_uncompressed;
  671.         r--;
  672.     case 2:
  673.         r->Type = S2SS_CSLIP_O_TCP;
  674.         r->String = "o_tcp";
  675.         r->Count = sdu->sdu_slcompress.sls_o_tcp;
  676.         r--;
  677.     case 1:
  678.         r->Type = S2SS_CSLIP_O_NONTCP;
  679.         r->String = "o_nontcp";
  680.         r->Count = sdu->sdu_slcompress.sls_o_nontcp;
  681.     case 0:
  682.         break;
  683.     }
  684.     
  685.     stats->RecordCountSupplied = count;
  686.     }
  687. #else
  688.     stats->RecordCountSupplied = 0;
  689. #endif
  690.     TermIO(ios2);
  691. }
  692.  
  693. /*
  694. ** This function returns the global statistics for the
  695. ** slip device.
  696. */
  697. VOID GetGlobalStats(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  698. {
  699.     struct Sana2DeviceStats *stats;
  700.  
  701.     stats = (struct Sana2DeviceStats *)ios2->ios2_StatData;
  702.  
  703.     stats->PacketsReceived    = sdu->sdu_Stats.PacketsReceived;
  704.     stats->PacketsSent        = sdu->sdu_Stats.PacketsSent;
  705.     stats->BadData        = sdu->sdu_Stats.BadData;
  706.     stats->Overruns        = sdu->sdu_Stats.Overruns;
  707.     stats->UnknownTypesReceived = sdu->sdu_Stats.UnknownTypesReceived;
  708.     stats->Reconfigurations    = sdu->sdu_Stats.Reconfigurations;
  709.     stats->LastStart.tv_secs    = sdu->sdu_Stats.LastStart.tv_secs;
  710.     stats->LastStart.tv_micro    = sdu->sdu_Stats.LastStart.tv_micro; /* Rhialto */
  711.  
  712.     /* Rhialto: huh?
  713.     ios2->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
  714.     ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  715.      */
  716.     TermIO(ios2);
  717. }
  718.  
  719. /*
  720. ** This function returns statistics for a specific
  721. ** type of packet that is being tracked.  Unfortunately,
  722. ** SLIP can't differentiate between different packet
  723. ** types, which makes packet type tracking essentially
  724. ** useless as the numbers would essentially be the same
  725. ** as those found via S2_GETGLOBALSTATS.
  726. **
  727. ** Just to be thourough, I have arbitrarily picked
  728. ** the packet type for SLIP IP packets to be 2048, the
  729. ** same as tha used for Ethernet.  This will at least
  730. ** allow you to track IP packets.
  731. */
  732. VOID GetTypeStats(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  733. {
  734.     struct Sana2PacketTypeStats *stats;
  735.     struct SuperS2PTStats *sstats;
  736.  
  737.     ObtainSemaphore(&sdu->sdu_ListLock);
  738.  
  739.     stats = (struct Sana2PacketTypeStats *)ios2->ios2_StatData;
  740.     sstats = (struct SuperS2PTStats *)sdu->sdu_Track.mlh_Head;
  741.  
  742.     while(sstats->ss_Node.mln_Succ)
  743.     {
  744.     if(ios2->ios2_PacketType == sstats->ss_PType)
  745.     {
  746.         stats->PacketsSent = sstats->ss_Stats.PacketsSent;
  747.         stats->PacketsReceived = sstats->ss_Stats.PacketsReceived;
  748.         stats->BytesSent = sstats->ss_Stats.BytesSent;
  749.         stats->BytesReceived = sstats->ss_Stats.BytesReceived;
  750.         stats->PacketsDropped = sstats->ss_Stats.PacketsDropped;
  751.         break;
  752.     }
  753.     sstats = (struct SuperS2PTStats *)sstats->ss_Node.mln_Succ;
  754.     }
  755.     ReleaseSemaphore(&sdu->sdu_ListLock);
  756.     if(!sstats->ss_Node.mln_Succ)
  757.     {
  758.     ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
  759.     ios2->ios2_WireError = S2WERR_NOT_TRACKED;
  760.     }
  761.     TermIO(ios2);
  762. }
  763.  
  764. /*
  765. ** This function adds a packet type to the list
  766. ** of those that are being tracked.
  767. */
  768. VOID TrackType(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  769. {
  770.     struct SuperS2PTStats *stats;
  771.  
  772.     ObtainSemaphore(&sdu->sdu_ListLock);
  773.  
  774.     stats = (struct SuperS2PTStats *)sdu->sdu_Track.mlh_Head;
  775.  
  776.     while(stats->ss_Node.mln_Succ)
  777.     {
  778.     if(ios2->ios2_PacketType == stats->ss_PType)
  779.     {
  780.         ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
  781.         ios2->ios2_WireError = S2WERR_ALREADY_TRACKED;
  782.         break;    /* Rhialto */
  783.     }
  784.     stats = (struct SuperS2PTStats *)stats->ss_Node.mln_Succ;
  785.     }
  786.     if(!stats->ss_Node.mln_Succ)
  787.     {
  788.     if(stats = AllocMem(sizeof(struct SuperS2PTStats),MEMF_CLEAR|MEMF_PUBLIC))
  789.     {
  790.         stats->ss_PType = ios2->ios2_PacketType;    /* Rhialto */
  791.         if(ios2->ios2_PacketType == 2048)
  792.         sdu->sdu_IPTrack = stats;
  793.         AddTail((struct List *)&sdu->sdu_Track,(struct Node *)stats);
  794.     }
  795.     }
  796.     ReleaseSemaphore(&sdu->sdu_ListLock);
  797.  
  798.     TermIO(ios2);
  799. }
  800.  
  801. /*
  802. ** This function removes a packet type from the
  803. ** list of those that are being tracked.
  804. */
  805. VOID UnTrackType(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  806. {
  807.     struct SuperS2PTStats *stats;
  808.     struct SuperS2PTStats *stats_next;
  809.  
  810.     ObtainSemaphore(&sdu->sdu_ListLock);
  811.  
  812.     stats = (struct SuperS2PTStats *)sdu->sdu_Track.mlh_Head;
  813.  
  814.     while(stats->ss_Node.mln_Succ)
  815.     {
  816.     stats_next = (struct SuperS2PTStats *)stats->ss_Node.mln_Succ;
  817.     if(ios2->ios2_PacketType == stats->ss_PType)
  818.     {
  819.         if(ios2->ios2_PacketType == 2048)
  820.         sdu->sdu_IPTrack = NULL;
  821.         Remove((struct Node *)stats);
  822.         FreeMem(stats,sizeof(struct SuperS2PTStats));
  823.         stats = NULL;
  824.         break;
  825.     }
  826.     stats = stats_next;
  827.     }
  828.     if(stats)
  829.     {
  830.     ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
  831.     ios2->ios2_WireError = S2WERR_NOT_TRACKED;
  832.     }
  833.     ReleaseSemaphore(&sdu->sdu_ListLock);
  834.  
  835.     TermIO(ios2);
  836. }
  837.  
  838. /*
  839. ** This function is called whenever we receive a packet
  840. ** from the serial device driver.
  841. **
  842. */
  843. VOID PacketReceived(struct SLIPDevUnit *sdu, ULONG length)
  844. {
  845.     sdu->sdu_Stats.PacketsReceived++;
  846.  
  847.     if(sdu->sdu_IPTrack)
  848.     {
  849.     sdu->sdu_IPTrack->ss_Stats.PacketsReceived++;
  850.     sdu->sdu_IPTrack->ss_Stats.BytesReceived+=length;
  851.     }
  852. }
  853.  
  854. /*
  855. ** This function is called whenever a packet is
  856. ** sent to the serial device driver.
  857. */
  858. VOID PacketSent(struct SLIPDevUnit *sdu, ULONG length)
  859. {
  860.     sdu->sdu_Stats.PacketsSent++;
  861.  
  862.     if(sdu->sdu_IPTrack)
  863.     {
  864.     sdu->sdu_IPTrack->ss_Stats.PacketsSent++;
  865.     sdu->sdu_IPTrack->ss_Stats.BytesSent+=length;
  866.     }
  867. }
  868.  
  869. /*
  870. ** This function is called whenever a packet that
  871. ** is too large is received.
  872. */
  873. VOID PacketOverrun(struct SLIPDevUnit *sdu)
  874. {
  875. #if CSLIP
  876.     sl_uncompress_tcp(NULL, TYPE_ERROR, &sdu->sdu_slcompress);
  877. #endif
  878.     sdu->sdu_Stats.Overruns++;
  879.     DoEvent(sdu, S2EVENT_RX);
  880. }
  881.  
  882. /*
  883. ** This function is called whenever a packet with
  884. ** garbage data is encountered.
  885. */
  886. VOID ReceivedGarbage(struct SLIPDevUnit *sdu)
  887. {
  888. #if CSLIP
  889.     sl_uncompress_tcp(NULL, TYPE_ERROR, &sdu->sdu_slcompress);
  890. #endif
  891.     sdu->sdu_Stats.BadData++;
  892.     DoEvent(sdu, S2EVENT_RX);
  893. }
  894.  
  895. /*
  896. ** This function is called whenever a packet
  897. ** is dropped by the SLIP driver.
  898. */
  899. VOID PacketDropped(struct SLIPDevUnit *sdu)
  900. {
  901.     if(sdu->sdu_IPTrack)
  902.     {
  903.     sdu->sdu_IPTrack->ss_Stats.PacketsDropped++;
  904.     }
  905. }
  906.  
  907. /*
  908. ** This function is used to return an IO request
  909. ** back to the sender.
  910. */
  911. VOID TermIO(struct IOSana2Req *ios2)
  912. {
  913.     if(!(ios2->ios2_Req.io_Flags & IOF_QUICK))
  914.     ReplyMsg((struct Message *)ios2);
  915. }
  916.  
  917. /*
  918. ** The device AbortIO() entry point.
  919. **
  920. ** A1 - The IO request to be aborted.
  921. ** A3 - The unit pointer NOT!
  922. ** A6 - The device base.
  923. */
  924. ULONG ASM DevAbortIO(REG(a1) struct IOSana2Req *ios2,
  925.              REG(a6) struct SLIPDevice *SLIPDevice)
  926. {
  927.     struct SLIPDevUnit *sdu = (struct SLIPDevUnit *)ios2->ios2_Req.io_Unit;
  928.     ULONG result = 0L;
  929.  
  930.     ObtainSemaphore(&sdu->sdu_ListLock);
  931.     if(ios2->ios2_Req.io_Message.mn_Node.ln_Type != NT_REPLYMSG)
  932.     {
  933.     switch(ios2->ios2_Req.io_Command)
  934.     {
  935.         case CMD_READ:    result=AbortReq(&sdu->sdu_Rx,ios2);
  936.                 break;
  937.  
  938.         case CMD_WRITE: result=AbortReq(&sdu->sdu_Tx,ios2);
  939.                 break;
  940.  
  941.         case S2_READORPHAN:    result=AbortReq(&sdu->sdu_RxOrph,ios2);
  942.                     break;
  943.  
  944.         case S2_ONEVENT:    result=AbortReq(&sdu->sdu_Events,ios2);
  945.                     break;
  946.  
  947.         default:        result=IOERR_NOCMD;
  948.                     break;
  949.     }
  950.     }
  951.     ReleaseSemaphore(&sdu->sdu_ListLock);
  952.     return(result);
  953. }
  954.  
  955. /*
  956. ** This funcion is used to locate an IO request in a linked
  957. ** list and abort it if found.
  958. */
  959. ULONG AbortReq(struct MinList *minlist, struct IOSana2Req *ios2)
  960. {
  961.     struct Node *node, *next;
  962.     ULONG result=IOERR_NOCMD;
  963.  
  964.     node = (struct Node *)minlist->mlh_Head;
  965.  
  966.     while(node->ln_Succ)
  967.     {
  968.     next = node->ln_Succ;
  969.  
  970.     if(node == (struct Node *)ios2)
  971.     {
  972.         Remove((struct Node *)ios2);
  973.         ios2->ios2_Req.io_Error = IOERR_ABORTED;
  974.         TermIO(ios2);
  975.         result = 0;
  976.     }
  977.     node = next;
  978.     }
  979.     return(result);
  980. }
  981.  
  982. /*
  983. ** This function handles S2_CONFIGINTERFACE commands.
  984. */
  985. VOID ConfigInterface(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  986. {
  987.  
  988.     /* Note: we may only be configured once. */
  989.     if(!(sdu->sdu_State & SLIPUF_CONFIG))
  990.     {
  991.     if(OpenSerial(sdu))
  992.     {
  993.         CopyMem(&sdu->sdu_StAddr,&ios2->ios2_SrcAddr,4);
  994.         sdu->sdu_State |= SLIPUF_CONFIG;
  995.     }
  996.     }
  997.     else
  998.     {
  999.     /* Sorry, we're already configured. */
  1000.     ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
  1001.     ios2->ios2_WireError = S2WERR_IS_CONFIGURED;
  1002.     }
  1003.     TermIO(ios2);
  1004. }
  1005.  
  1006. /*
  1007. ** This function handles S2_GETSTATIONADDRESS commands.
  1008. **
  1009. ** We don't really have a hardware address, so we will
  1010. ** just clear the source address field.
  1011. ** Rhialto: What we want is the config file address as hardware
  1012. *8        address, and the S2_CONFIGINTERFACE address as current address.
  1013. */
  1014.  
  1015. VOID GetStationAddress(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  1016. {
  1017.     memset(ios2->ios2_DstAddr, 0, SANA2_MAX_ADDR_BYTES);
  1018.     memset(ios2->ios2_SrcAddr, 0, SANA2_MAX_ADDR_BYTES);
  1019.     memcpy(ios2->ios2_SrcAddr, &sdu->sdu_StAddr, 4);
  1020.     memcpy(ios2->ios2_DstAddr, &sdu->sdu_HwAddr, 4);
  1021.  
  1022.     TermIO(ios2);
  1023. }
  1024.  
  1025. /*
  1026. ** This function handles S2_DEVICEQUERY comands.
  1027. ** Rhialto: Give the format of the data, and the *correct* size!
  1028. */
  1029. VOID DeviceQuery(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  1030. {
  1031.     struct Sana2DeviceQuery *sdq;
  1032.  
  1033.     sdq = (struct Sana2DeviceQuery *)ios2->ios2_StatData;
  1034.  
  1035.     sdq->DevQueryFormat = 0;
  1036.     sdq->DeviceLevel = 0;
  1037.     sdq->AddrFieldSize = 32;            /* 32-bit IP address */
  1038.     sdq->MTU = sdu->sdu_MTU;            /* ppessi: configureable MTU */
  1039.     sdq->BPS = sdu->sdu_BaudRate;
  1040. #if CSLIP
  1041.     sdq->HardwareType = S2WireType_CSLIP;
  1042. #else
  1043.     sdq->HardwareType = S2WireType_SLIP;
  1044. #endif
  1045.  
  1046.     sdq->SizeSupplied = sizeof(*sdq);
  1047.     TermIO(ios2);
  1048. }
  1049.  
  1050. /*
  1051. ** This function is used for handling CMD_WRITE
  1052. ** commands.
  1053. */
  1054. VOID WritePacket(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  1055. {
  1056.  
  1057.     /* Make sure that we are online. */
  1058.     if(sdu->sdu_State & SLIPUF_ONLINE)
  1059.     {
  1060.     /* Make sure it's a legal length. */
  1061.     if(ios2->ios2_DataLength <= sdu->sdu_MTU)
  1062.     {
  1063.         /* See if our serial CMD_WRITE command is busy.  If it's not, send
  1064.            the IO request to SendPacket. */
  1065.         if(CheckIO((struct IORequest *)sdu->sdu_SerTx))
  1066.         {
  1067.         WaitIO((struct IORequest *)sdu->sdu_SerTx);
  1068.         /* See if modem have dropped carrier */
  1069.         if (sdu->sdu_State & SLIPUF_CD) 
  1070.         {
  1071.             sdu->sdu_SerTx->IOSer.io_Command = SDCMD_QUERY;
  1072.             if(DoIO((struct IORequest *)sdu->sdu_SerTx) ||
  1073.                (sdu->sdu_SerTx->io_Status & (1 << 5)))
  1074.             {
  1075.             /* We're online, so shut everything down. */
  1076.             CloseSerial(sdu);
  1077.             DoOffline(sdu);
  1078.             DoEvent(sdu, S2EVENT_OFFLINE);
  1079.             debug(("Carrier Dropped\n"));
  1080.  
  1081.             /* Sorry, we're offline */
  1082.             ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  1083.             ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  1084.             TermIO(ios2);
  1085.             return;
  1086.             }
  1087.         }
  1088.         SendPacket(sdu, ios2);
  1089.         }
  1090.         else
  1091.         {
  1092.         /* We'll have to queue the packet for later...*/
  1093.         ios2->ios2_Req.io_Flags &= ~IOF_QUICK;
  1094.         ObtainSemaphore(&sdu->sdu_ListLock);
  1095. #if USEPRIORITY
  1096.         Enqueue((struct List *)&sdu->sdu_Tx,(struct Node *)ios2);
  1097. #else
  1098.         AddTail((struct List *)&sdu->sdu_Tx,(struct Node *)ios2);
  1099. #endif
  1100.         ReleaseSemaphore(&sdu->sdu_ListLock);
  1101.         }
  1102.     }
  1103.     else
  1104.     {
  1105.         /* Sorry, the packet is too long! */
  1106.         ios2->ios2_Req.io_Error = S2ERR_MTU_EXCEEDED;
  1107.         ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  1108.         TermIO(ios2);
  1109.         DoEvent(sdu, S2EVENT_TX);
  1110.     }
  1111.     }
  1112.     else
  1113.     {
  1114.     /* Sorry, we're offline */
  1115.     ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  1116.     ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  1117.     TermIO(ios2);
  1118.     DoEvent(sdu, S2EVENT_TX);
  1119.     }
  1120. }
  1121.  
  1122. VOID SendPacket(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  1123. {
  1124.     struct IOExtSer *ioser;
  1125.     struct BufferManagement *bm;
  1126.     ULONG framelength;
  1127.  
  1128.     bm =(struct BufferManagement *) ios2->ios2_BufferManagement;
  1129.  
  1130.     /* Copy the data out of the packet into our temporary buffer. */
  1131.     if((*bm->bm_CopyFromBuffer)(sdu->sdu_TxBuff,ios2->ios2_Data,ios2->ios2_DataLength))
  1132.     {
  1133. #if CSLIP
  1134.     struct mbuf m;
  1135.     unsigned char type;
  1136.  
  1137.     m.m_off = sdu->sdu_TxBuff;
  1138.     m.m_len = ios2->ios2_DataLength;
  1139.  
  1140.     /* Appendix B.1  Living without a framing `type' byte */
  1141.  
  1142.     type = sl_compress_tcp(&m, &sdu->sdu_slcompress);
  1143.     m.m_off[0] |= type;
  1144.  
  1145.     /* Encode the packet in SLIP format */
  1146.     framelength=EncodeSLIP(m.m_off,sdu->sdu_TxSLIP,m.m_len);
  1147.     PacketSent(sdu,m.m_len);
  1148. #else
  1149.     /* Encode the packet in SLIP format */
  1150.     framelength=EncodeSLIP(sdu->sdu_TxBuff,sdu->sdu_TxSLIP,ios2->ios2_DataLength);
  1151.     PacketSent(sdu,ios2->ios2_DataLength);
  1152. #endif
  1153.  
  1154.     ioser = sdu->sdu_SerTx;
  1155.     ioser->IOSer.io_Data = sdu->sdu_TxSLIP;
  1156.     ioser->IOSer.io_Length = framelength;
  1157.     ioser->IOSer.io_Command = CMD_WRITE;
  1158.     ioser->IOSer.io_Error = 0;
  1159.     ioser->IOSer.io_Message.mn_Node.ln_Type = 0;
  1160.  
  1161.     /* Send the packet to the serial device driver */
  1162.     SendIO((struct IORequest *)ioser);
  1163.     }
  1164.     else
  1165.     {
  1166.     /* Something went wrong...*/
  1167.     ios2->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
  1168.     ios2->ios2_WireError = S2WERR_BUFF_ERROR;
  1169.     DoEvent(sdu,S2EVENT_BUFF);
  1170.     }
  1171.     TermIO(ios2);
  1172. }
  1173.  
  1174. /*
  1175. ** This routine encodes a packet in SLIP format.
  1176. **
  1177. ** The format is quite simple.
  1178. **
  1179. ** SLIP Encoding:
  1180. **
  1181. ** SLIP_ESC    -> SLIP_ESC SLIP_ESC_ESC
  1182. ** SLIP_END    -> SLIP_ESC SLIP_ESC_END
  1183. **
  1184. ** The packet is preceded and terminated with a SLIP_END as prescribed by
  1185. ** rfc 1055.
  1186. **
  1187. */
  1188. ULONG EncodeSLIP(UBYTE *source, UBYTE *dest, ULONG length)
  1189. {
  1190.     UBYTE ch;
  1191.     UBYTE *current;
  1192.  
  1193.     current = dest;
  1194.  
  1195.     *current = SLIP_END;
  1196.     current++;
  1197.  
  1198.     while(length--)
  1199.     {
  1200.     ch = *source;
  1201.     source++;
  1202.  
  1203.     if(ch == SLIP_ESC)
  1204.     {
  1205.         *current = SLIP_ESC;
  1206.         current++;
  1207.         ch = SLIP_ESC_ESC;
  1208.     }
  1209.     else if(ch == SLIP_END)
  1210.     {
  1211.         *current = SLIP_ESC;
  1212.         current ++;
  1213.         ch = SLIP_ESC_END;
  1214.     }
  1215.     *current = ch;
  1216.     current++;
  1217.     }
  1218.     *current = SLIP_END;
  1219.     current++;
  1220.  
  1221.     return((ULONG)(current - dest));
  1222. }
  1223.  
  1224. /*
  1225. ** This routine handles CMD_READ commands.  We
  1226. ** always queue these unless we're offline.
  1227. */
  1228. VOID ReadPacket(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  1229. {
  1230.  
  1231.     if(sdu->sdu_State & SLIPUF_ONLINE)
  1232.     {
  1233.     /* Queue it... */
  1234.     ObtainSemaphore(&sdu->sdu_ListLock);
  1235.     AddTail((struct List *)&sdu->sdu_Rx,(struct Node *)ios2);
  1236. #if DEMANDREAD
  1237.     if (sdu->sdu_SerRx->IOSer.io_Message.mn_Node.ln_Type == NT_FREEMSG)
  1238.         QueueSerRequest(sdu);
  1239. #endif
  1240.     ReleaseSemaphore(&sdu->sdu_ListLock);
  1241.     }
  1242.     else
  1243.     {
  1244.     /* Sorry, we're offline */
  1245.     ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  1246.     ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  1247.     TermIO(ios2);
  1248.     DoEvent(sdu, S2EVENT_RX);
  1249.     }
  1250. }
  1251.  
  1252. /*
  1253. ** This routine handles CMD_READORPHAN commands.  We
  1254. ** always queue these unless we're offline.
  1255. **
  1256. ** Note: These IO requests will never get satisfied.
  1257. **     Since SLIP doesn't contain packet type information,
  1258. **     there is no way to identify what type of packets
  1259. **     are being received or sent.  Thus, we simply ignore
  1260. **     the packet type and *assume* that the packets are
  1261. **     IP packets.
  1262. */
  1263. VOID ReadOrphan(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  1264. {
  1265.  
  1266.     if(sdu->sdu_State & SLIPUF_ONLINE)
  1267.     {
  1268.     /* Queue it...*/
  1269.     ObtainSemaphore(&sdu->sdu_ListLock);
  1270.     AddTail((struct List *)&sdu->sdu_RxOrph,(struct Node *)ios2);
  1271. #if DEMANDREAD
  1272.     if (sdu->sdu_SerRx->IOSer.io_Message.mn_Node.ln_Type == NT_FREEMSG)
  1273.         QueueSerRequest(sdu);
  1274. #endif
  1275.     ReleaseSemaphore(&sdu->sdu_ListLock);
  1276.     }
  1277.     else
  1278.     {
  1279.     /* Sorry, we're offline */
  1280.     ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  1281.     ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  1282.     DoEvent(sdu, S2EVENT_RX);
  1283.     TermIO(ios2);
  1284.     }
  1285. }
  1286.  
  1287. /*
  1288. ** This routine initializes our IO requests and buffers
  1289. ** for serial i/o and SLIP encoding/decoding.
  1290. */
  1291. BOOL InitSerial(struct SLIPDevUnit *sdu)
  1292. {
  1293.     ULONG *clr;
  1294.     BOOL status = FALSE;
  1295.  
  1296.     for(clr = (ULONG *) &sdu->sdu_SerRx; clr <= (ULONG *) &sdu->sdu_TxSLIP; clr++)
  1297.     *clr = 0L;
  1298.  
  1299.     if(sdu->sdu_TxPort = CreateMsgPort())
  1300.     {
  1301.     if(sdu->sdu_SerTx = CreateIORequest(sdu->sdu_TxPort,sizeof(struct IOExtSer)))
  1302.     {
  1303.         if(sdu->sdu_RxPort = CreateMsgPort())
  1304.         {
  1305.         if(sdu->sdu_SerRx = CreateIORequest(sdu->sdu_RxPort,sizeof(struct IOExtSer)))
  1306.         {
  1307.             if(sdu->sdu_TxBuff = AllocVec((sdu->sdu_MTU + BUF_SLOP) * 2 + MAX_HDR, MEMF_CLEAR|MEMF_PUBLIC))
  1308.             {
  1309.             sdu->sdu_RxBuff = sdu->sdu_TxBuff + sdu->sdu_MTU + BUF_SLOP + MAX_HDR;
  1310.             sdu->sdu_RxBuffPtr = sdu->sdu_RxBuff;
  1311.  
  1312.             if(sdu->sdu_TxSLIP = AllocVec((sdu->sdu_MTU * 2 + BUF_SLOP) * 2, MEMF_CLEAR|MEMF_PUBLIC))
  1313.             {
  1314.                 sdu->sdu_RxSLIP = sdu->sdu_TxSLIP + sdu->sdu_MTU * 2 + BUF_SLOP;
  1315.                 {
  1316.                 status = TRUE;
  1317.                 }
  1318.             }
  1319.             }
  1320.         }
  1321.         }
  1322.     }
  1323.     }
  1324.     if(!status)
  1325.     DeinitSerial(sdu);
  1326.     return(status);
  1327. }
  1328.  
  1329. /*
  1330. ** This routine cleans up our serial i/o requests
  1331. ** and misc. buffers.
  1332. */
  1333. VOID DeinitSerial(struct SLIPDevUnit *sdu)
  1334. {
  1335.     if(sdu->sdu_SerTx)
  1336.     DeleteIORequest(sdu->sdu_SerTx);
  1337.  
  1338.     if(sdu->sdu_TxPort)
  1339.     DeleteMsgPort(sdu->sdu_TxPort);
  1340.  
  1341.     if(sdu->sdu_SerRx)
  1342.     DeleteIORequest(sdu->sdu_SerRx);
  1343.  
  1344.     if(sdu->sdu_RxPort)
  1345.     DeleteMsgPort(sdu->sdu_RxPort);
  1346.  
  1347.     if(sdu->sdu_TxBuff)
  1348.     FreeVec(sdu->sdu_TxBuff);
  1349.  
  1350.     if(sdu->sdu_TxSLIP)
  1351.     FreeVec(sdu->sdu_TxSLIP);
  1352. }
  1353.  
  1354. /*
  1355. ** This routine handles S2_ONEVNET commands.
  1356. */
  1357. VOID OnEvent(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  1358. {
  1359.  
  1360.     switch(ios2->ios2_WireError)
  1361.     {
  1362.     /* Special case.  We may already be online, in which
  1363.        case the IO request should return immediately. Otherwise
  1364.        we queue it for later. */
  1365.  
  1366.     case S2EVENT_ONLINE:
  1367.                 if(sdu->sdu_State & SLIPUF_ONLINE)
  1368.                     TermIO(ios2);
  1369.                 else
  1370.                 {
  1371.                     ObtainSemaphore(&sdu->sdu_ListLock);
  1372.                     AddTail((struct List *)&sdu->sdu_Events,(struct Node *)ios2);
  1373.                     ReleaseSemaphore(&sdu->sdu_ListLock);
  1374.                 }
  1375.                 break;
  1376.  
  1377.     /* Same as with S2EVENT_ONLINE, but the opposite
  1378.        happens. */
  1379.     case S2EVENT_OFFLINE:
  1380.                 if(sdu->sdu_State & SLIPUF_ONLINE)
  1381.                 {
  1382.                     ObtainSemaphore(&sdu->sdu_ListLock);
  1383.                     AddTail((struct List *)&sdu->sdu_Events,(struct Node *)ios2);
  1384.                     ReleaseSemaphore(&sdu->sdu_ListLock);
  1385.                 }
  1386.                 else
  1387.                     TermIO(ios2);
  1388.                 break;
  1389.  
  1390.     /* Just queue everything else. */
  1391.     default:
  1392.                 ObtainSemaphore(&sdu->sdu_ListLock);
  1393.                 AddTail((struct List *)&sdu->sdu_Events,(struct Node *)ios2);
  1394.                 ReleaseSemaphore(&sdu->sdu_ListLock);
  1395.                 break;
  1396.     }
  1397. }
  1398.  
  1399. /*
  1400. ** This routine opens the serial device driver and attempts to bring
  1401. ** the device online.
  1402. */
  1403. BOOL OpenSerial(struct SLIPDevUnit *sdu)
  1404. {
  1405.     BOOL status = TRUE;
  1406.     ULONG odflags;
  1407.  
  1408.     sdu->sdu_SerRx->IOSer.io_Device = NULL;
  1409.  
  1410.     odflags = SERF_XDISABLED | SERF_RAD_BOOGIE;
  1411.     if(sdu->sdu_State & SLIPUF_7WIRE)
  1412.     odflags |= SERF_7WIRE;
  1413.  
  1414.     /* Rhialto: odflags must be in io_SerFlags, not in OpenDevice! */
  1415.     sdu->sdu_SerTx->io_SerFlags = odflags;
  1416.  
  1417.     if(!OpenDevice(sdu->sdu_SerDevName,sdu->sdu_SerUnitNum,(struct IORequest *)sdu->sdu_SerTx,0))
  1418.     {
  1419.     /* Set up our serial parameters */
  1420.     sdu->sdu_SerRx->IOSer.io_Device = sdu->sdu_SerTx->IOSer.io_Device;
  1421.     sdu->sdu_SerRx->IOSer.io_Unit = sdu->sdu_SerTx->IOSer.io_Unit;
  1422.  
  1423.     sdu->sdu_SerTx->IOSer.io_Command = SDCMD_SETPARAMS;
  1424.     sdu->sdu_SerTx->io_Baud = sdu->sdu_BaudRate;
  1425.     sdu->sdu_SerTx->io_RBufLen = SLIP_SERIAL_BUFSIZE;
  1426.     sdu->sdu_SerTx->io_ReadLen = 8;
  1427.     sdu->sdu_SerTx->io_WriteLen = 8;
  1428.     sdu->sdu_SerTx->io_StopBits = 1;
  1429.     sdu->sdu_SerTx->io_SerFlags = odflags;
  1430.     sdu->sdu_SerTx->io_TermArray.TermArray0 =
  1431.         sdu->sdu_SerTx->io_TermArray.TermArray1 = 0x01010101 * (UBYTE)SLIP_END;
  1432.  
  1433.     if(!DoIO((struct IORequest *)sdu->sdu_SerTx))
  1434.     {
  1435.         /* Are we checking for serial detect? */
  1436.         if(sdu->sdu_State & SLIPUF_CD)
  1437.         {
  1438.         sdu->sdu_SerTx->IOSer.io_Command = SDCMD_QUERY;
  1439.         if(!DoIO((struct IORequest *)sdu->sdu_SerTx))
  1440.         {
  1441.             if(sdu->sdu_SerTx->io_Status & (1 << 5))
  1442.             {
  1443.             /* Sorry, no carrier, shut down the serial driver
  1444.                and set our state to offline. */
  1445.             /* ppessi: remove CloseDevice -- use status instead */
  1446.             status = FALSE;    
  1447.             debug(("No Carrier\n"));
  1448.             }
  1449.         }
  1450.         else
  1451.         {
  1452.             status = FALSE;
  1453.             debug(("QUERY failed %d\n",sdu->sdu_SerTx->io_Error));
  1454.         }
  1455.         } 
  1456.         if (status)
  1457.         {
  1458.         /* We're now online */
  1459.         sdu->sdu_State |= SLIPUF_ONLINE;
  1460.         MarkTimeOnline(sdu);
  1461.  
  1462.         /* Queue up the initial CMD_READ command for the
  1463.            serial driver. */
  1464.         sdu->sdu_SerRx->IOSer.io_Command = CMD_READ;
  1465.         sdu->sdu_SerRx->IOSer.io_Length = 1;
  1466.         sdu->sdu_SerRx->IOSer.io_Data = sdu->sdu_RxSLIP;
  1467.         if(sdu->sdu_State & SLIPUF_EOFMODE)
  1468.           odflags |= SERF_EOFMODE;
  1469.         sdu->sdu_SerRx->io_SerFlags = odflags;
  1470.         sdu->sdu_SerRx->io_TermArray.TermArray0 =
  1471.             sdu->sdu_SerRx->io_TermArray.TermArray1 = 0x01010101 * (UBYTE)SLIP_END;
  1472.         SendIO((struct IORequest *)sdu->sdu_SerRx);
  1473.         }
  1474.     }
  1475.     else
  1476.     {
  1477.         status = FALSE;
  1478.         debug(("SETPARAMS failed %d\n",sdu->sdu_SerTx->io_Error));
  1479.     }
  1480.  
  1481.     if (!status)
  1482.         CloseDevice((struct IORequest *)sdu->sdu_SerTx);
  1483.     }
  1484.     else
  1485.     {
  1486.     struct Library *IntuitionBase;
  1487.     struct EasyStruct es;
  1488.     ULONG args[2];
  1489.     args[0]=(ULONG)sdu->sdu_SerDevName;
  1490.     args[1]=(ULONG)sdu->sdu_SerUnitNum;
  1491.     if(IntuitionBase = OpenLibrary("intuition.library",37L))
  1492.     {
  1493.         es.es_StructSize=sizeof(struct EasyStruct);
  1494.         es.es_Flags=0;
  1495.         es.es_Title=(char *)SLIPName;
  1496.         es.es_TextFormat="Couldn't open %s unit %ld.";
  1497.         es.es_GadgetFormat="Okay";
  1498.         EasyRequestArgs(NULL, &es, 0, (APTR)args);
  1499.         CloseLibrary(IntuitionBase);
  1500.     }
  1501.     status = FALSE;
  1502.     }
  1503.  
  1504.     return(status);
  1505. }
  1506.  
  1507. /*
  1508. ** This routine gets the current system time and stores
  1509. ** it in our global statistics structure.
  1510. */
  1511.  
  1512. VOID MarkTimeOnline(struct SLIPDevUnit *sdu)
  1513. {
  1514.     register struct Library *TimerBase;
  1515.     struct timerequest *treq;
  1516.  
  1517.     if(treq = (struct timerequest *)AllocMem(sizeof(struct timerequest),MEMF_PUBLIC|MEMF_CLEAR))
  1518.     {
  1519.     if(!OpenDevice("timer.device",UNIT_MICROHZ,(struct IORequest *)treq,0L))
  1520.     {
  1521.         TimerBase = (struct Library *)treq->tr_node.io_Device;
  1522.         GetSysTime(&sdu->sdu_Stats.LastStart);
  1523.         CloseDevice((struct IORequest *)treq);
  1524.     }
  1525.     FreeMem(treq,sizeof(struct timerequest));
  1526.     }
  1527. }
  1528.  
  1529. /*
  1530. ** This routine aborts any pending activity with the serial
  1531. ** device driver and then brings the slip driver offline.
  1532. */
  1533. VOID CloseSerial(struct SLIPDevUnit *sdu)
  1534. {
  1535.     if (!CheckIO((struct IORequest *)sdu->sdu_SerRx) && 
  1536.     sdu->sdu_SerRx->IOSer.io_Message.mn_Node.ln_Type != NT_FREEMSG) {
  1537.     AbortIO((struct IORequest *)sdu->sdu_SerRx);
  1538.     WaitIO((struct IORequest *)sdu->sdu_SerRx);
  1539.     }
  1540.     while(GetMsg(sdu->sdu_RxPort));
  1541.  
  1542.     if (!CheckIO((struct IORequest *)sdu->sdu_SerTx)) {
  1543.     AbortIO((struct IORequest *)sdu->sdu_SerTx);
  1544.     WaitIO((struct IORequest *)sdu->sdu_SerTx);
  1545.     }
  1546.     while(GetMsg(sdu->sdu_TxPort));
  1547.  
  1548.     CloseDevice((struct IORequest *)sdu->sdu_SerRx);
  1549.  
  1550.     sdu->sdu_State &= ~SLIPUF_ONLINE;
  1551. }
  1552.  
  1553. /*
  1554. ** This routime handles CMD_ONLINE commands.
  1555. */
  1556. VOID Online(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  1557. {
  1558.  
  1559.     if(!(sdu->sdu_State & SLIPUF_ONLINE))
  1560.     {
  1561.     /* We're offline. Try to go online. */
  1562.     if(OpenSerial(sdu))
  1563.     {
  1564.         if(sdu->sdu_State & SLIPUF_ONLINE)
  1565.         {
  1566.         /* In case someone wants to know...*/
  1567.         DoEvent(sdu, S2EVENT_ONLINE);
  1568.         }
  1569.         else
  1570.         {
  1571.         /* Sorry, the attempt to go online failed. */
  1572.         ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  1573.         ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  1574.         }
  1575.     }
  1576.     else
  1577.     {
  1578.         /* A general problem occured. */
  1579.         ios2->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
  1580.         ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  1581.     }
  1582.     }
  1583.     TermIO(ios2);
  1584. }
  1585.  
  1586. /*
  1587. ** This routine handles CMD_OFFLINE commands.
  1588. */
  1589. VOID Offline(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  1590. {
  1591.     TermIO(ios2);
  1592.  
  1593.     if(sdu->sdu_State & SLIPUF_ONLINE)
  1594.     {
  1595.     /* We're online, so shut everything down. */
  1596.     CloseSerial(sdu);
  1597.     DoOffline(sdu);
  1598.     DoEvent(sdu,S2EVENT_OFFLINE);
  1599.     }
  1600. }
  1601.  
  1602. /*
  1603. ** This routine is called whenever an "important"
  1604. ** SANA-II event occurs.
  1605. */
  1606. VOID DoEvent(struct SLIPDevUnit *sdu, ULONG event)
  1607. {
  1608.     struct IOSana2Req *ios2;
  1609.     struct IOSana2Req *ios2_next;
  1610.  
  1611.     ObtainSemaphore(&sdu->sdu_ListLock);
  1612.  
  1613.     ios2 = (struct IOSana2Req *)sdu->sdu_Events.mlh_Head;
  1614.  
  1615.     while(ios2->ios2_Req.io_Message.mn_Node.ln_Succ)
  1616.     {
  1617.     ios2_next = (struct IOSana2Req *)ios2->ios2_Req.io_Message.mn_Node.ln_Succ;
  1618.  
  1619.     /* Is this the event they are looking for? */
  1620.     if(ios2->ios2_WireError == event)
  1621.     {
  1622.         Remove((struct Node *)ios2);
  1623.         TermIO(ios2);
  1624.     }
  1625.     ios2 = ios2_next;
  1626.     }
  1627.     ReleaseSemaphore(&sdu->sdu_ListLock);
  1628. }
  1629.  
  1630. /*
  1631. ** This routine is called whenever the device needs to
  1632. ** be taken offline.  We return any pending CMD_READ's
  1633. ** or CMD_WRITE's to their senders.
  1634. */
  1635. VOID DoOffline(struct SLIPDevUnit *sdu)
  1636. {
  1637.     struct IOSana2Req *ios2;
  1638.  
  1639.     ObtainSemaphore(&sdu->sdu_ListLock);
  1640.  
  1641.     while(ios2 = (struct IOSana2Req *)RemHead((struct List *)&sdu->sdu_Rx))
  1642.     {
  1643.     ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  1644.     ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  1645.     TermIO(ios2);
  1646.     }
  1647.  
  1648.     while(ios2 = (struct IOSana2Req *)RemHead((struct List *)&sdu->sdu_Tx))
  1649.     {
  1650.     ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  1651.     ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  1652.     TermIO(ios2);
  1653.     }
  1654.     ReleaseSemaphore(&sdu->sdu_ListLock);
  1655. }
  1656.  
  1657. /*
  1658. ** This routine is called whenever a CMD_WRITE request
  1659. ** has returned from the serial driver.
  1660. */
  1661. VOID ServiceTxPort(struct SLIPDevUnit *sdu)
  1662. {
  1663.     struct IOSana2Req *ios2;
  1664.  
  1665.     /* See if we have any pending CMD_WRITE requests. */
  1666.     if(sdu->sdu_State & SLIPUF_ONLINE)
  1667.     {
  1668.     ObtainSemaphore(&sdu->sdu_ListLock);
  1669.     ios2 = (struct IOSana2Req *)RemHead((struct List *)&sdu->sdu_Tx);
  1670.     ReleaseSemaphore(&sdu->sdu_ListLock);
  1671.     if(ios2)
  1672.     {
  1673.         SendPacket(sdu, ios2);
  1674.     }
  1675.     }
  1676. }
  1677.  
  1678. /*
  1679. ** This routine is called whenever a CMD_READ request
  1680. ** returns from the serial driver.  It decodes the
  1681. ** packet data and tries to build complete packets.
  1682. */
  1683. VOID DoSerial(struct SLIPDevUnit *sdu, struct IOExtSer *ioSer)
  1684. {
  1685.     UBYTE *rx_ptr,*packet_ptr;
  1686.     UBYTE rx_byte, packet_byte;
  1687.     ULONG length;
  1688.  
  1689.     packet_ptr = sdu->sdu_RxBuffPtr;
  1690.     rx_ptr = sdu->sdu_RxSLIP;
  1691.  
  1692.     length = ioSer->IOSer.io_Actual;    /* Rhialto: Was io_Length */
  1693.  
  1694.     while(length--)
  1695.     {
  1696.     rx_byte = packet_byte = *rx_ptr;
  1697.     rx_ptr++;
  1698.  
  1699.     /* Handle SLIP packet decoding...*/
  1700.     if(sdu->sdu_Escape)
  1701.     {
  1702.         if(rx_byte == SLIP_ESC_ESC)
  1703.         packet_byte = SLIP_ESC;
  1704.         else if(rx_byte = SLIP_ESC_END)
  1705.         packet_byte = SLIP_END;
  1706.         else
  1707.         ReceivedGarbage(sdu);           /* This packet may be hosed */
  1708.  
  1709.         sdu->sdu_Escape = FALSE;
  1710.     }
  1711.     else if(rx_byte == SLIP_ESC)
  1712.     {
  1713.         sdu->sdu_Escape = TRUE;
  1714.         continue;
  1715.     }
  1716.     else if(rx_byte == SLIP_END)
  1717.     {
  1718.         GotPacket(sdu,(ULONG)(packet_ptr - sdu->sdu_RxBuff));
  1719.         packet_ptr = sdu->sdu_RxBuff;
  1720.         continue;
  1721.     }
  1722.     *packet_ptr = packet_byte;
  1723.     packet_ptr++;
  1724.  
  1725.     if(((ULONG)(packet_ptr - sdu->sdu_RxBuff)) > sdu->sdu_MTU)
  1726.     {
  1727.         packet_ptr = sdu->sdu_RxBuff;
  1728.         PacketOverrun(sdu);
  1729.     }
  1730.     }
  1731.     sdu->sdu_RxBuffPtr = packet_ptr;
  1732.  
  1733.     /* Queue up another CMD_READ request...*/
  1734. #if DEMANDREAD
  1735.     /* Rhialto: but only if we are sure that we won't drop that packet */
  1736.     ObtainSemaphore(&sdu->sdu_ListLock);
  1737.     /* Semaphore protection of sdu_Rx, sdu_RxOrph, and sdu_Tx is not
  1738.      * really necessary, since they are only accessed from the
  1739.      * Unit task, because there are no IMMEDIATE device commands.
  1740.      */
  1741.     /* Semaphore protection *is* needed due AbortIO //ppessi */
  1742.     if (!IsListEmpty((struct List *)&sdu->sdu_Rx) ||
  1743.     !IsListEmpty((struct List *)&sdu->sdu_RxOrph))
  1744.     QueueSerRequest(sdu);
  1745.     else
  1746.     sdu->sdu_SerRx->IOSer.io_Message.mn_Node.ln_Type = NT_FREEMSG;
  1747.     ReleaseSemaphore(&sdu->sdu_ListLock);
  1748. #else
  1749.     QueueSerRequest(sdu);
  1750. #endif
  1751. }
  1752.  
  1753. /*
  1754. ** This routine is called whenever we think we've got
  1755. ** a complete packet to satisfy a CMD_READ request.
  1756. */
  1757. VOID GotPacket(struct SLIPDevUnit *sdu, ULONG length)
  1758. {
  1759.     struct IOSana2Req *ios2;
  1760.     struct BufferManagement *bm;
  1761.  
  1762.     /* We ignore zero-length packets. These occur
  1763.        in between legal SLIP packets due to the
  1764.        way SLIP packets are framed. */
  1765.  
  1766.     if(length)
  1767.     {
  1768.     short orphan;
  1769.  
  1770.     PacketReceived(sdu,length);
  1771.     ObtainSemaphore(&sdu->sdu_ListLock);
  1772.  
  1773.     ios2 = (struct IOSana2Req *)RemHead((struct List *)&sdu->sdu_Rx);
  1774.  
  1775.         if (orphan = ios2 == NULL) 
  1776.         ios2 = (struct IOSana2Req *)RemHead((struct List *)&sdu->sdu_RxOrph);
  1777.  
  1778.     ReleaseSemaphore(&sdu->sdu_ListLock);
  1779.  
  1780.     if(ios2)
  1781.     {
  1782. #if CSLIP
  1783.         /* Appendix B.1  Living without a framing `type' byte */
  1784.         struct mbuf m;
  1785.         unsigned char type;
  1786.  
  1787.         m.m_off = sdu->sdu_RxBuff;
  1788.         m.m_len = length;
  1789.  
  1790.         type = m.m_off[0];
  1791.  
  1792.         if (type & 0x80)
  1793.         type = TYPE_COMPRESSED_TCP;
  1794.         else if (type >= 0x70) {
  1795.         type = TYPE_UNCOMPRESSED_TCP;
  1796.         m.m_off[0] &= ~0x30;
  1797.         } else
  1798.         type = TYPE_IP;
  1799.         if (NULL == sl_uncompress_tcp(&m, type, &sdu->sdu_slcompress)) 
  1800.         {
  1801.         /* put the ios2 back to queue or they will be lost //ppessi */
  1802.         ObtainSemaphore(&sdu->sdu_ListLock);
  1803.         if (orphan) 
  1804.             AddHead((struct List *)&sdu->sdu_RxOrph, (struct Node*)ios2);
  1805.         else
  1806.             AddHead((struct List *)&sdu->sdu_Rx, (struct Node*)ios2);
  1807.         ReleaseSemaphore(&sdu->sdu_ListLock);
  1808.         return;
  1809.         }
  1810.         bm = (struct BufferManagement *)ios2->ios2_BufferManagement;
  1811.  
  1812.         /* Copy the data into the protocol stack's buffer using its
  1813.            supplied callback routine. */
  1814.         if((*bm->bm_CopyToBuffer)(ios2->ios2_Data,m.m_off,m.m_len))
  1815.         {
  1816.         ios2->ios2_DataLength = m.m_len;
  1817.         }
  1818. #else
  1819.         bm = (struct BufferManagement *)ios2->ios2_BufferManagement;
  1820.  
  1821.         /* Copy the data into the protocol stack's buffer using its
  1822.            supplied callback routine. */
  1823.         if((*bm->bm_CopyToBuffer)(ios2->ios2_Data,sdu->sdu_RxBuff,length))
  1824.         {
  1825.         ios2->ios2_DataLength = length;
  1826.         }
  1827. #endif
  1828.         else
  1829.         {
  1830.         ios2->ios2_DataLength = 0;
  1831.         ios2->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
  1832.         ios2->ios2_WireError = S2WERR_BUFF_ERROR;
  1833.         DoEvent(sdu,S2EVENT_BUFF);
  1834.         }
  1835.         TermIO(ios2);
  1836.     }
  1837.     else
  1838.         PacketDropped(sdu);
  1839.     }
  1840.     sdu->sdu_Escape = 0;
  1841. }
  1842.  
  1843. /*
  1844. ** This routine is called whenever we need to
  1845. ** get more data from the serial port.    We first
  1846. ** to a SDCMD_QUERY to see how much data is available,
  1847. ** if any.
  1848. ** Rhialto: without EOF mode, this makes the thing a real CPU hog,
  1849. ** as long as input is coming in and read requests are pending.
  1850. ** And since it runs at pri 5, that is a real disaster.
  1851. */
  1852. VOID QueueSerRequest(struct SLIPDevUnit *sdu)
  1853. {
  1854.     if ((sdu->sdu_State & SLIPUF_EOFMODE) == 0 || (sdu->sdu_State & SLIPUF_CD))
  1855.     {
  1856.     sdu->sdu_SerRx->IOSer.io_Command = SDCMD_QUERY;
  1857.     DoIO((struct IORequest *)sdu->sdu_SerRx);
  1858.  
  1859.     if (sdu->sdu_State & SLIPUF_CD)
  1860.     {
  1861.         if (sdu->sdu_SerRx->io_Status & (1<<5))
  1862.         {
  1863.         /* Oops! We've lost carrier. Go offline. */
  1864.         CloseSerial(sdu);
  1865.         DoOffline(sdu);
  1866.         DoEvent(sdu,S2EVENT_OFFLINE);
  1867.         return;
  1868.         }
  1869.     }
  1870.     }
  1871.     
  1872.     sdu->sdu_SerRx->IOSer.io_Command = CMD_READ;
  1873.     sdu->sdu_SerRx->IOSer.io_Data = sdu->sdu_RxSLIP;
  1874.     
  1875.     if (sdu->sdu_State & SLIPUF_EOFMODE) 
  1876.     {
  1877.     sdu->sdu_SerRx->IOSer.io_Length = sdu->sdu_MTU * 2 + 1;
  1878.     }
  1879.     else
  1880.     {
  1881.     /* Rhialto: This could lead to requesting more than the buffer
  1882.      * size! The serial.device has a 16K buffer. (See SDCMD_SETPARAMS)
  1883.      */
  1884.     sdu->sdu_SerRx->IOSer.io_Length = sdu->sdu_SerRx->IOSer.io_Actual;
  1885.  
  1886.     if (sdu->sdu_SerRx->IOSer.io_Length > (sdu->sdu_MTU * 2 + BUF_SLOP))
  1887.         sdu->sdu_SerRx->IOSer.io_Length = (sdu->sdu_MTU * 2 + BUF_SLOP);
  1888.     else
  1889.         /* If the number of bytes available is zero, queue a request
  1890.            for one byte. */
  1891.         if(!sdu->sdu_SerRx->IOSer.io_Length)
  1892.         sdu->sdu_SerRx->IOSer.io_Length = 1;
  1893.     }
  1894.  
  1895.     SendIO((struct IORequest *)sdu->sdu_SerRx);
  1896. }
  1897.  
  1898. /*
  1899. ** This is the C entry point for the Unit process.
  1900. */
  1901.  
  1902. VOID ASM DevProcCEntry(VOID)
  1903. {
  1904.     struct Process *proc;
  1905.     struct SLIPDevUnit *sdu;
  1906.     struct IOExtSer *ioser;
  1907.     struct StartupMessage *sm;
  1908.     struct BufferManagement *bm;
  1909.     struct IOSana2Req *ios2;
  1910.     ULONG waitmask, signals;
  1911.     UBYTE signalbit;
  1912.  
  1913.     /* Find our Process pointer and wait for our startup
  1914.        message to arrive. */
  1915.  
  1916.     proc = (struct Process *)FindTask(0L);
  1917.  
  1918.     WaitPort(&proc->pr_MsgPort);
  1919.  
  1920.     /* Pull the startup message off of our process messageport. */
  1921.     sm = (struct StartupMessage *)GetMsg(&proc->pr_MsgPort);
  1922.  
  1923.     /* Grab our Unit pointer. */
  1924.     sdu = (struct SLIPDevUnit *)sm->Unit;
  1925.  
  1926.     /* Attempt to allocate a signal bit for our Unit MsgPort. */
  1927.     signalbit = AllocSignal(-1L);
  1928.     if(signalbit != -1)
  1929.     {
  1930.     /* Set up our Unit's MsgPort. */
  1931.     sdu->sdu_Unit.unit_MsgPort.mp_SigBit = signalbit;
  1932.     sdu->sdu_Unit.unit_MsgPort.mp_SigTask = (struct Task *)proc;
  1933.     sdu->sdu_Unit.unit_MsgPort.mp_Flags = PA_SIGNAL;
  1934.  
  1935.     /* Initialize our list semaphore */
  1936.     InitSemaphore(&sdu->sdu_ListLock);
  1937.  
  1938.     /* Initialize our linked lists. */
  1939.     NewList((struct List *)&sdu->sdu_Rx);
  1940.     NewList((struct List *)&sdu->sdu_RxOrph);
  1941.     NewList((struct List *)&sdu->sdu_Tx);
  1942.     NewList((struct List *)&sdu->sdu_Events);
  1943.     NewList((struct List *)&sdu->sdu_BuffMgmt);
  1944.     NewList((struct List *)&sdu->sdu_Track);
  1945.  
  1946. #if CSLIP
  1947.     /* Initialise the compression stuff */
  1948.     sl_compress_init(&sdu->sdu_slcompress, 16, 16);
  1949. #endif
  1950.  
  1951.     /* Initialize the serial stuff.  If all goes okay,
  1952.        set sdu->sdu_Proc to pointer to our unit process.
  1953.        This will let the Unit init code know that were
  1954.        are okay. */
  1955.  
  1956.     if(InitSerial(sdu))
  1957.         sdu->sdu_Proc = proc;
  1958.     }
  1959.     /* Reply to our startup message */
  1960.     ReplyMsg((struct Message *)sm);
  1961.  
  1962.     /* Check sdu->sdu_Proc to see if everything went okay up
  1963.        above. */
  1964.     if(sdu->sdu_Proc)
  1965.     {
  1966.     waitmask = (1L<<signalbit) | (1L<<sdu->sdu_RxPort->mp_SigBit) |
  1967.            (1L<<sdu->sdu_TxPort->mp_SigBit) | SIGBREAKF_CTRL_F;
  1968.  
  1969.     /* Loop...*/
  1970.     while (TRUE)
  1971.     {
  1972.         int More;
  1973.  
  1974.         signals = Wait(waitmask);
  1975.  
  1976.         /* Have we been signaled to shut down? */
  1977.         if (signals & SIGBREAKF_CTRL_F)
  1978.         break;
  1979.  
  1980.         do {
  1981.         More = FALSE;
  1982.  
  1983.         if (ios2 = (struct IOSana2Req *)GetMsg((struct MsgPort *)sdu))
  1984.         {
  1985.             More = TRUE;
  1986.             PerformIO(ios2);
  1987.         }
  1988.         if (ioser = (struct IOExtSer *)GetMsg(sdu->sdu_RxPort))
  1989.         {
  1990.             More = TRUE;
  1991.             if(sdu->sdu_State & SLIPUF_ONLINE)
  1992.             {
  1993.             DoSerial(sdu, ioser);
  1994.             }
  1995.         }
  1996.         if (ioser = (struct IOExtSer *)GetMsg(sdu->sdu_TxPort))
  1997.         {
  1998.             More = TRUE;
  1999.             ServiceTxPort(sdu);
  2000.         }
  2001.         } while (More);
  2002.     }
  2003.     /* If we're online, we need to shut everything down. */
  2004.     if(sdu->sdu_State & SLIPUF_ONLINE)
  2005.     {
  2006.         CloseSerial(sdu);
  2007.         FreeSignal(signalbit);
  2008.         while(bm = (struct BufferManagement *)RemHead((struct List *)&sdu->sdu_BuffMgmt))
  2009.         FreeMem(bm, sizeof(struct BufferManagement));
  2010.  
  2011.     }
  2012.     DeinitSerial(sdu);
  2013. #if CSLIP
  2014.     sl_compress_deinit(&sdu->sdu_slcompress);
  2015. #endif
  2016.  
  2017.     /* Signal the other side we're exiting.  Make sure that
  2018.        we exit before they wake up by using the same trick
  2019.        when replying to Workbench startup messages. */
  2020.  
  2021.     Forbid();
  2022.     Signal((struct Task *)sdu->sdu_Proc, SIGBREAKF_CTRL_F);
  2023.     }
  2024.     /* Something went wrong in the init code.  Drop out. */
  2025.     else
  2026.     {
  2027.     if(signalbit)
  2028.         FreeSignal(signalbit);
  2029.     }
  2030. }
  2031.  
  2032. /* List init routine. */
  2033. VOID NewList(struct List *list)
  2034. {
  2035.     list->lh_Head = (struct Node *)&list->lh_Tail;
  2036.     list->lh_Tail = NULL;
  2037.     list->lh_TailPred = (struct Node *)list;
  2038. }
  2039.